package com.github_Dididipapa.shortlink.admin.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github_Dididipapa.shortlink.admin.common.enums.BaseErrorCode;
import com.github_Dididipapa.shortlink.admin.common.exception.ClientException;
import com.github_Dididipapa.shortlink.admin.common.result.R;
import com.github_Dididipapa.shortlink.admin.common.result.Rs;
import com.github_Dididipapa.shortlink.admin.dao.entity.Group;
import com.github_Dididipapa.shortlink.admin.dao.entity.User;
import com.github_Dididipapa.shortlink.admin.dao.mapper.groupMapper;
import com.github_Dididipapa.shortlink.admin.dao.mapper.UserMapper;
import com.github_Dididipapa.shortlink.admin.dto.req.UserLoginReqDTO;
import com.github_Dididipapa.shortlink.admin.dto.resp.UserLoginRespDTO;
import com.github_Dididipapa.shortlink.admin.dto.resp.UserRespDTO;
import com.github_Dididipapa.shortlink.admin.service.UserService;
import com.github_Dididipapa.shortlink.admin.toolkit.RandomCodeGenerator;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.Duration;
import java.util.Date;
import java.util.UUID;

/**
 * @description: To be defined
 * @author: dididi_papa
 * @email: mitis1624087624@gmail.com
 * @date: 2025/09/09  14:04
 */
@RequiredArgsConstructor
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource(name = "RBloom-user")
    private final RBloomFilter<String> usernameFilter;
    private final RedissonClient redisson;
    private final RedisTemplate<String, Object> redisTemplate;
    private final UserMapper userMapper;
    private final groupMapper groupMapper;


    @Override
    public R getUserByUsername(String username) {
        return Rs.success(userMapper.getUserByUsername(username));
    }

    @Override
    public R existUsername(String username) {
        if (userMapper.exists(new QueryWrapper<User>().eq("username", username))) return Rs.success();
        return Rs.failure();
    }

    @Transactional
    @Override
    public R registerUser(User user) throws IOException {
        RLock lock = redisson.getLock("register_" + user.getUsername());
        lock.lock();
        try {
            // 双检判断用户名是否存在
            if (usernameFilter.contains(user.getUsername())){
                if (userMapper.exists(new QueryWrapper<User>().eq("username", user.getUsername()))) {
                    return Rs.failure(BaseErrorCode.USER_NAME_EXIST_ERROR.code(),
                            BaseErrorCode.USER_NAME_EXIST_ERROR.message());
                }
            }
            user.setDelFlag(0);
            user.setCreateTime(new Date());
            user.setUpdateTime(new Date());
            userMapper.save(user);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //创建用户默认分组信息
            Group group = Group.builder()
                    .gid(RandomCodeGenerator.generateRandomCode())
                    .name("default")
                    .username(user.getUsername())
                    .sortOrder(1)
                    .createTime(new Date())
                    .updateTime(new Date())
                    .delFlag(0)
                    .build();
            groupMapper.save(group);
            usernameFilter.add(user.getUsername());
            lock.unlock();
        }
        UserRespDTO userRespDTO = new UserRespDTO();
        BeanUtils.copyProperties(user, userRespDTO);
        return Rs.success(userRespDTO);
    }

    @Override
    public UserLoginRespDTO login(UserLoginReqDTO user) {
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .eq("username", user.getUsername())
                .eq("password", user.getPassword());
        User target = baseMapper.selectOne(wrapper);
        if (target == null) throw new ClientException("用户登录异常");
        String uuid = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(uuid, JSON.toJSONString(target), Duration.ofHours(1));
        return new UserLoginRespDTO(uuid);
    }

    @Override
    public Boolean checkLogin(String token, String usrername) {
        User user = JSON.parseObject((String) redisTemplate.opsForValue().get(token), User.class);
        return user != null && user.getUsername().equals(usrername);
    }

    @Override
    public Boolean logOut(String token, String usrername) {
        User user = JSON.parseObject((String) redisTemplate.opsForValue().get(token), User.class);
        if (user != null && user.getUsername().equals(usrername)) {
            redisTemplate.delete(token);
            return true;
        }
        return false;
    }


}
